import { _decorator, Component, Node } from 'cc';
import { BaseManager } from '../../libs/rxjs/cc3/BaseManager';
import { sys } from 'cc';
import { ReactiveProperty } from '../../libs/rxjs/cc3/ReactiveProperty';
import { color } from 'cc';
import { director } from 'cc';
import { System } from 'cc';
import { jsb_sdk_m } from './JsbSDKManager';
import { Observable, Subscriber } from 'rxjs';
import { thinking_sdk_m } from './ThinkingCocosSDKManager';
import { gm } from '../GameManager';
import { udm } from '../UserDataManager';
import { timem } from '../TimeManager';
import { am } from '../AudioManager';
import { appsflyer_sdk_m } from './AppsFlyerSDKManager';
import { ReactiveSet } from '../../libs/rxjs/cc3/ReactiveSet';
import { MergeASAP } from '../../libs/rxjs/cc3/Merge';
const { ccclass, property } = _decorator;

@ccclass('AppLovinCocosSDKManager')
export class AppLovinCocosSDKManager extends BaseManager {

    public static instance: AppLovinCocosSDKManager;
    static ID = 'applovin_sdk_system';
    get logColorOverride() { return color().fromHEX('#EECCDD') };

    infoDic = ReactiveProperty.Create<Record<string, any>>(null);
    idfa = ReactiveProperty.Create<string>(null);
    ata = ReactiveProperty.Create<string>(null);

    stageNum = ReactiveProperty.Create<number>(0); // 广告埋点所统计的stageNum，只有下一关的开始才算

    bannerShowReasons = ReactiveSet.Create();

    static registerSystem() {
        director.unregisterSystem(director.getSystem(AppLovinCocosSDKManager.ID));
        director.registerSystem(AppLovinCocosSDKManager.ID, applovin_sdk_m, System.Priority.MEDIUM);
        applovin_sdk_m.init();
    }

    useObserves() {
        return [
            MergeASAP(udm.noAds, this.bannerShowReasons).subscribe(_ => {
                if (udm.noAds.value > 0) {
                    this.requestRemoveBannerAd();
                } else {
                    if (this.bannerShowReasons.size > 0) {
                        this.requestCreateBannerAd();
                    } else {
                        this.requestHideBannerAd();
                    }
                }
            })
        ];
    }

    onInitManager() {
        this.log('onInitManager', this.timestamp);
        if (sys.isNative) {
            jsb_sdk_m.registerMsg('AppLovinCocosSDKManager.isReadyInterstitialAd', this.isReadyInterstitialAd.bind(this));
            jsb_sdk_m.registerMsg('AppLovinCocosSDKManager.load_InterstitialAd', this.load_InterstitialAd.bind(this));
            jsb_sdk_m.registerMsg('AppLovinCocosSDKManager.didLoad_InterstitialAd', this.didLoad_InterstitialAd.bind(this));
            jsb_sdk_m.registerMsg('AppLovinCocosSDKManager.didFailToLoadAd_InterstitialAd', this.didFailToLoadAd_InterstitialAd.bind(this));
            jsb_sdk_m.registerMsg('AppLovinCocosSDKManager.didDisplay_InterstitialAd', this.didDisplay_InterstitialAd.bind(this));
            jsb_sdk_m.registerMsg('AppLovinCocosSDKManager.didClick_InterstitialAd', this.didClick_InterstitialAd.bind(this));
            jsb_sdk_m.registerMsg('AppLovinCocosSDKManager.didHide_InterstitialAd', this.didHide_InterstitialAd.bind(this));
            jsb_sdk_m.registerMsg('AppLovinCocosSDKManager.didFail_InterstitialAd', this.didFail_InterstitialAd.bind(this));

            jsb_sdk_m.registerMsg('AppLovinCocosSDKManager.isReadyRewardedAd', this.isReadyRewardedAd.bind(this));
            jsb_sdk_m.registerMsg('AppLovinCocosSDKManager.load_RewardedAd', this.load_RewardedAd.bind(this));
            jsb_sdk_m.registerMsg('AppLovinCocosSDKManager.didLoad_RewardedAd', this.didLoad_RewardedAd.bind(this));
            jsb_sdk_m.registerMsg('AppLovinCocosSDKManager.didFailToLoadAd_RewardedAd', this.didFailToLoadAd_RewardedAd.bind(this));
            jsb_sdk_m.registerMsg('AppLovinCocosSDKManager.didDisplay_RewardedAd', this.didDisplay_RewardedAd.bind(this));
            jsb_sdk_m.registerMsg('AppLovinCocosSDKManager.didClick_RewardedAd', this.didClick_RewardedAd.bind(this));
            jsb_sdk_m.registerMsg('AppLovinCocosSDKManager.didHide_RewardedAd', this.didHide_RewardedAd.bind(this));
            jsb_sdk_m.registerMsg('AppLovinCocosSDKManager.didFail_RewardedAd', this.didFail_RewardedAd.bind(this));
            jsb_sdk_m.registerMsg('AppLovinCocosSDKManager.didRewardUser_RewardedAd', this.didRewardUser_RewardedAd.bind(this));

            jsb_sdk_m.registerMsg('AppLovinCocosSDKManager.load_BannerAd', this.load_BannerAd.bind(this));
            jsb_sdk_m.registerMsg('AppLovinCocosSDKManager.didLoad_BannerAd', this.didLoad_BannerAd.bind(this));
            jsb_sdk_m.registerMsg('AppLovinCocosSDKManager.didFailToLoadAd_BannerAd', this.didFailToLoadAd_BannerAd.bind(this));
            jsb_sdk_m.registerMsg('AppLovinCocosSDKManager.didDisplay_BannerAd', this.didDisplay_BannerAd.bind(this)); // 并没有这个，banner的load在自己的adview里面，不确定是否diddisplay
            jsb_sdk_m.registerMsg('AppLovinCocosSDKManager.didClick_BannerAd', this.didClick_BannerAd.bind(this));


            jsb_sdk_m.registerMsg('AppLovinCocosSDKManager.didPayRevenue', this.didPayRevenue.bind(this));
        }

        this.stageNum.value = udm.stageNum.value;
    }

    requestDebugger() {
        jsb_sdk_m.sendMsg('AppLovinCocosSDK.showMediationDebugger', '{}');
    }

    // interstitial ad

    _observer_interstitial_isReady: Subscriber<boolean> = null;
    requestIsReadyInterstitialAd(): Observable<boolean> {
        return new Observable(observer => {
            this._observer_interstitial_isReady = observer;
            jsb_sdk_m.sendMsg('AppLovinCocosSDK.isReadyInterstitialAd', '{}');
        });
    }

    requestCreateInterstitialAd() {
        jsb_sdk_m.sendMsg('AppLovinCocosSDK.createInterstitialAd', '{}');
    }

    requestShowInterstitialAd() {
        jsb_sdk_m.sendMsg('AppLovinCocosSDK.showInterstitialAd', '{}');
    }

    private isReadyInterstitialAd(param: string) {
        this.log('@isReadyInterstitialAd', param);
        let { isReady } = JSON.parse(param);
        if (this._observer_interstitial_isReady != null) {
            this._observer_interstitial_isReady.nextAndComplete(isReady);
            this._observer_interstitial_isReady = null;
        }
    }

    interstitialad_load_at = null;
    private load_InterstitialAd(param: string) {
        this.log('load_InterstitialAd');
        thinking_sdk_m.requestTrack('Ads_Request', {
            Ad_format: 'INTER',
            Ad_From: 'Max',
            ad_progress: gm.interstitialAdLoadFailed.value ? 'LoadNone' : 'Load',
            Level_ID: udm.stageNum.value
        });
        this.interstitialad_load_at = timem.now();
    }

    private didLoad_InterstitialAd(param: string) {
        this.log('@didLoad_InterstitialAd');
        gm.interstitialAdLoadFailed.value = false;
        thinking_sdk_m.requestTrack('Ads_Load', {
            Ad_format: 'INTER',
            Ads_Duration: Math.floor((timem.now() - this.interstitialad_load_at) / 1000),
            Ad_From: 'Max',
            ad_progress: 'Load',
            Level_ID: udm.stageNum.value
        });
    }

    private didFailToLoadAd_InterstitialAd(param: string) {
        this.log('@didFailToLoadAd_InterstitialAd');
        gm.interstitialAdLoadFailed.value = true;
        let { adUnitIdentifier, errMessage } = JSON.parse(param);
        thinking_sdk_m.requestTrack('Ads_Load', {
            Ad_format: 'INTER',
            Ads_Duration: Math.floor((timem.now() - this.interstitialad_load_at) / 1000),
            Ad_From: 'Max',
            ad_progress: 'LoadFail',
            Error_Info: errMessage,
            ad_unit_name: adUnitIdentifier,
            Level_ID: udm.stageNum.value
        });
    }

    private didDisplay_InterstitialAd(param: string) {
        this.log('@didDisplay_InterstitialAd');
        let { networkName } = JSON.parse(param);

        udm.interstitialAdTimes.value++;
        udm.interstitialAt.value = timem.now();
        udm.save();

        am.pauseReasons.add('interstitial_ad');

        this.payRevenueCache.value = JSON.parse(param);
        let { adUnitIdentifier, placement, revenue, revenuePrecision, countryCode, adFormat } = this.payRevenueCache.value;

        thinking_sdk_m.requestUserAdd({
            InterNum: 1
        });
        thinking_sdk_m.requestTrack('Ads_Interstitial', {
            AdsType: gm.currentInterstitialAdsType.value,
            Times: udm.interstitialAdTimes.value,
            Ad_From: 'Max',
            AdNetwork: networkName,
            precision: revenuePrecision,
            currency: 'usd',
            ad_revenue: revenue,
            OpenUI: gm.currentAdsOpenUI.value,
            IsNew: udm.isNew.value,
            Level_ID: gm.winStageInfo.value?.stageId,
        });
        appsflyer_sdk_m.logEvent('af_InsertionADs');
        if (appsflyer_sdk_m.InsertionAD_Xs.has(udm.interstitialAdTimes.value)) {
            appsflyer_sdk_m.logEvent(`af_InsertionADs_${udm.interstitialAdTimes.value}`);
        }
    }

    private didClick_InterstitialAd(param: string) {
        this.log('@didClick_InterstitialAd');
    }

    private didHide_InterstitialAd(param: string) {
        this.log('@didHide_InterstitialAd');
        gm.interstitialAdDidHide.execute();
        am.pauseReasons.delete('interstitial_ad');
    }

    private didFail_InterstitialAd(param: string) {
        this.log('@didFail_InterstitialAd', param);
        let { code, message } = JSON.parse(param);
    }

    // rewarded ad

    _observer_rewarded_isReady: Subscriber<boolean> = null;
    requestIsReadyRewardedAd(): Observable<boolean> {
        return new Observable(observer => {
            this._observer_rewarded_isReady = observer;
            jsb_sdk_m.sendMsg('AppLovinCocosSDK.isReadyRewardedAd', '{}');
        });
    }

    requestCreateRewardedAd() {
        jsb_sdk_m.sendMsg('AppLovinCocosSDK.createRewardedAd', '{}');
    }

    _observer_rewarded: Subscriber<boolean> = null;
    _didReward: boolean = null;

    requestShowRewardedAd(): Observable<boolean> {
        return new Observable(observer => {
            this._observer_rewarded = observer;
            this._didReward = false;
            jsb_sdk_m.sendMsg('AppLovinCocosSDK.showRewardedAd', '{}');
        });
    }

    isReadyRewardedAd(param: string) {
        this.log('@isReadyRewardedAd', param, this._observer_rewarded_isReady == null);
        let { isReady } = JSON.parse(param);
        if (this._observer_rewarded_isReady != null) {
            this._observer_rewarded_isReady.nextAndComplete(isReady);
            this._observer_rewarded_isReady = null;
        }
    }

    rewardedad_load_at = null;
    private load_RewardedAd(param: string) {
        this.log('load_RewardedAd');
        thinking_sdk_m.requestTrack('Ads_Request', {
            Ad_format: 'REWARDED',
            Ad_From: 'Max',
            ad_progress: gm.rewardedAdLoadFailed.value ? 'LoadNone' : 'Load',
            Level_ID: udm.stageNum.value
        });
        this.rewardedad_load_at = timem.now();
    }

    private didLoad_RewardedAd(param: string) {
        this.log('@didLoad_RewardedAd');
        gm.rewardedAdLoadFailed.value = false;
        thinking_sdk_m.requestTrack('Ads_Load', {
            Ad_format: 'REWARDED',
            Ads_Duration: Math.floor((timem.now() - this.rewardedad_load_at) / 1000),
            Ad_From: 'Max',
            ad_progress: 'Load',
            Level_ID: udm.stageNum.value
        });
    }

    private didFailToLoadAd_RewardedAd(param: string) {
        this.log('@didFailToLoadAd_RewardedAd');
        gm.rewardedAdLoadFailed.value = true;
        let { errMessage } = JSON.parse(param);
        thinking_sdk_m.requestTrack('Ads_Load', {
            Ad_format: 'REWARDED',
            Ads_Duration: Math.floor((timem.now() - this.rewardedad_load_at) / 1000),
            Ad_From: 'Max',
            ad_progress: 'LoadFail',
            Error_Info: errMessage,
            Level_ID: udm.stageNum.value
        });
    }

    private didDisplay_RewardedAd(param: string) {
        this.log('@didDisplay_RewardedAd');
        let { networkName } = JSON.parse(param);

        udm.rewardedAdTimes.value++;
        udm.save();

        am.pauseReasons.add('rewarded_ad');

        thinking_sdk_m.requestUserAdd({
            RvAdsNum: 1
        });

        this.payRevenueCache.value = JSON.parse(param);
        let { adUnitIdentifier, placement, revenue, revenuePrecision, countryCode, adFormat } = this.payRevenueCache.value;

        thinking_sdk_m.requestTrack('Ads_Suc', {
            AdsType: gm.currentAdsType.value,
            Ad_From: 'MAX',
            AdNetwork: networkName,
            precision: revenuePrecision,
            currency: 'usd',
            ad_revenue: revenue,
            OpenUI: gm.currentAdsOpenUI.value,
            IsNew: udm.isNew.value
        });

        appsflyer_sdk_m.logEvent('af_AdRewardAD');
        if (appsflyer_sdk_m.AdRewardAD_Xs.has(udm.rewardedAdTimes.value)) {
            appsflyer_sdk_m.logEvent(`af_AdRewardAD_${udm.rewardedAdTimes.value}`);
        }

    }

    private didClick_RewardedAd(param: string) {
        this.log('@didClick_RewardedAd');
    }

    private didHide_RewardedAd(param: string) {
        this.log('@didHide_RewardedAd');
        let { networkName } = JSON.parse(param);

        am.pauseReasons.delete('rewarded_ad');

        if (this._observer_rewarded != null) {
            this._observer_rewarded.nextAndComplete(this._didReward);
            this._observer_rewarded = null;
        }
    }

    private didFail_RewardedAd(param: string) {
        this.log('@didFail_RewardedAd', param);
        let { code, message } = JSON.parse(param);
        if (this._observer_rewarded != null) {
            this._observer_rewarded.nextAndComplete(this._didReward);
            this._observer_rewarded = null;
        }
    }

    private didRewardUser_RewardedAd(param: string) {
        this.log('@didRewardUser_RewardedAd', param);
        let { label, amount, description } = JSON.parse(param);
        this._didReward = true;
    }

    // banner ad
    _requestLoad = true;
    requestCreateBannerAd() {
        jsb_sdk_m.sendMsg('AppLovinCocosSDK.createBannerAd', '{}');
        this._requestLoad = true;
    }

    requestHideBannerAd() {
        jsb_sdk_m.sendMsg('AppLovinCocosSDK.hideBannerAd', '{}');
    }

    requestRemoveBannerAd() {
        jsb_sdk_m.sendMsg('AppLovinCocosSDK.removeBannerAd', '{}');
    }


    banner_load_at = null;
    load_BannerAd() {
        this.log("@load_BannerAd")
        thinking_sdk_m.requestTrack('Ads_Request', {
            Ad_format: 'BANNER',
            Ad_From: 'Max',
            ad_progress: gm.interstitialAdLoadFailed.value ? 'LoadNone' : 'Load',
            Level_ID: udm.stageNum.value
        });
        this.banner_load_at = timem.now();
    }

    didLoad_BannerAd() {
        this.log("@didLoad_BannerAd")
        gm.bannerAdLoadFailed.value = false;
        udm.bannerAdTimes.value++;
        udm.save();
        if (this._requestLoad) {
            thinking_sdk_m.requestTrack('Ads_Suc', {
                AdsType: gm.currentAdsType.value,
                Times: udm.bannerAdTimes.value,
                IsNew: udm.isNew.value
            });
            thinking_sdk_m.requestTrack('Ads_Load', {
                Ad_format: 'BANNER',
                Ads_Duration: Math.floor((timem.now() - this.banner_load_at) / 1000),
                Ad_From: 'Max',
                ad_progress: 'Load',
                Level_ID: udm.stageNum.value
            });
        }
    }

    didFailToLoadAd_BannerAd() {
        this.log("@didFailToLoadAd_BannerAd")
        gm.bannerAdLoadFailed.value = true;
            thinking_sdk_m.requestTrack('Ads_Load', {
                Ad_format: 'BANNER',
                Ads_Duration: Math.floor((timem.now() - this.banner_load_at) / 1000),
                Ad_From: 'Max',
                ad_progress: 'Fail',
                Level_ID: udm.stageNum.value
            });
    }

    didDisplay_BannerAd() {
        this.log("@didDisplay_BannerAd")
    }

    didClick_BannerAd() {
        this.log("@didClick_BannerAd")
    }

    payRevenueCache = ReactiveProperty.Create<{ adUnitIdentifier, placement, networkName, revenue, revenuePrecision, countryCode, adFormat }>(null);
    private didPayRevenue(param: string) {
        this.log('@didPayRevenue', param);
        this.payRevenueCache.value = JSON.parse(param);
        let { adUnitIdentifier, placement, networkName, revenue, revenuePrecision, countryCode, adFormat } = this.payRevenueCache.value;
        thinking_sdk_m.requestTrack('Ad_Revenue_Postback', {
            Level_ID: Math.min(applovin_sdk_m.stageNum.value, udm.stageNum.value),
            Ad_format: adFormat,
            AdNetwork: networkName,
            Ad_From: 'Max',
            ad_unit_name: adUnitIdentifier,
            precision: revenuePrecision,
            currency: 'usd',
            ad_revenue: revenue,
            countrycode: countryCode,
            IsNew: udm.isNew.value,
        });

        appsflyer_sdk_m.logEvent('af_ad_revenue'); // 之前的af_Activation改成了这个
    }

}

globalThis.AppLovinCocosSDKManager = AppLovinCocosSDKManager;

export const applovin_sdk_m = AppLovinCocosSDKManager.instance = new AppLovinCocosSDKManager();